﻿/*
 				________________________________COPYRIGHT_______________________________________
				Die Veröffentlichung dieses Objektes ist Illegal und wird strafrechtlich verfolgt
				werden. Sollte es zu einer Veröffentlichung kommen werden wir die Daten des
				Herrausgebers fündig machen und Anzeige erstatten. Desweiteren ist
				auch jeglicher Besitz dieses Objektes Illegal und kann ebenfalls als Grund für
				eine Anzeige verwendet werden.
				Ausnahmen der veröffentlichung und verleihung gelten nur wenn der Grundbesitzer
				diese durchführt.
				Die Uhrheberrechte dieses Objektes liegen der Entwickler Gruppe CyberScripting vor. 
                © 2011.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using System.Runtime.Serialization.Formatters.Binary;

namespace cubeworld
{
    class Data
    {
        public static SamplerState st = new SamplerState();

        public static Random random = new Random();
        public static SpriteBatch spriteBatch;
        public static GraphicsDeviceManager graphics;
        public static GraphicsDevice graphicsDevice;
        public static ContentManager content;
        public static CubeModel cubeModel;
        public static World.World world;
        public static FPSCounter fpsCounter;
        public static Entity.PlayerEntity player;

        public static SpriteFont debugFont;
        public static SpriteFont errorFont;
        public static SpriteFont titleFont;
        public static Texture2D kreuz;
        public static Texture2D logo;
        public static Texture2D buttonNormal;
        public static Texture2D buttonHover;
        public static Texture2D bg50;
        public static Texture2D knob, bar;
        public static Texture2D check, box;
        public static Effect instancedEffect;

        public static bool isDebugMode;

        public static Camera camera;
        public static int renderDistance = 30;

        public static Screen currentScreen = new ScreenManager.TitleScreen();
        public static Screen overlayScreen = null;

        public static Vector2 kreuzPos;

        /// <summary>
        /// Setzt die Klasse auf
        /// </summary>
        /// <param name="sb">Das SpriteBatch zum zeichnen von Texturen und Texten.</param>
        /// <param name="ct">Der Content Manager zum laden von Texturen, 3D Objekten usw.</param>
        /// <param name="gc">Der Graphics Device Manager.</param>
        /// <param name="gd">Das Graphics Device.</param>
        public static void SetUp(SpriteBatch sb, ContentManager ct, GraphicsDeviceManager gc, GraphicsDevice gd)
        {
            camera = new Camera(new Vector3(20, 14, 40), Vector3.Zero, 1000.0f);
            camera.SetUpMovement(true, true, 1.05f, 0.005f);
            st.Filter = TextureFilter.Point;
            content = ct;
            Translator.set_up();
            Translator.setLanguage(0);
            spriteBatch = sb;
            graphics = gc;
            graphicsDevice = gd;
            fpsCounter = new FPSCounter();
            World.BiomList.SetUp();
            player = new Entity.PlayerEntity("Test");

            cubeModel = new CubeModel();

            instancedEffect = content.Load<Effect>("effects\\InstancedModel");
            instancedEffect.CurrentTechnique = instancedEffect.Techniques["HardwareInstancing"];
            instancedEffect.Parameters["TextureAtlas"].SetValue(content.Load<Texture2D>("BlockTextures\\texture_atlas"));
            debugFont = content.Load<SpriteFont>("fonts\\debug");
            errorFont = content.Load<SpriteFont>("fonts\\error");
            kreuz = content.Load<Texture2D>("GUI\\kreuz");
            logo = content.Load<Texture2D>("GUI\\cubeworlds_logo");
            buttonNormal = content.Load<Texture2D>("GUI\\buttonNormal");
            buttonHover = content.Load<Texture2D>("GUI\\buttonHover");
            bg50 = content.Load<Texture2D>("GUI\\50bg");
            knob = Data.content.Load<Texture2D>("GUI\\knob");
            bar = Data.content.Load<Texture2D>("GUI\\bar");
            check = Data.content.Load<Texture2D>("GUI\\check");
            box = Data.content.Load<Texture2D>("GUI\\box");
            kreuzPos = new Vector2(graphics.PreferredBackBufferWidth * 0.5f - 10, graphics.PreferredBackBufferHeight * 0.5f - 10);

            currentScreen.Init();

            // JUST FOR TESTING PURPOSES!
            /*
            #region
            string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\save.world";
            if (System.IO.File.Exists(path))
            {
                System.IO.Stream stream = System.IO.File.Open(path, System.IO.FileMode.Open);

                System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                world = (World)formatter.Deserialize(stream);

                stream.Close();
            }
            #endregion
            */
        }

        public static void DrawString(SpriteFont font, string text, Vector2 position, Color color)
        {
            string s = "";
            string[] ss = text.Split(' ');
            foreach (string sss in ss)
            {
                s = s + Translator.translate(sss) + " ";
            }
            spriteBatch.DrawString(font, s, position, color);
        }

        /// <summary>
        /// Updatet den Aktuellen Screen
        /// </summary>
        /// <param name="elapsedTime">Die vergangene Zeit seit dem letzten Update.</param>
        public static void Update(float elapsedTime)
        {
#if !DEBUG
            try
            {
                if (overlayScreen != null)
                {
                    overlayScreen.Update(elapsedTime);
                }
                else
                {
                    currentScreen.Update(elapsedTime);
                }
            }
            catch (CubeWorldsException ex)
            {
                CloseOverlayScreen();
                SetScreen(new ScreenManager.CrashScreen(ex));
            }
            catch (Exception e)
            {
                CloseOverlayScreen();
                SetScreen(new ScreenManager.CrashScreen(e));
            }
#endif
#if DEBUG
            if (overlayScreen != null)
            {
                overlayScreen.Update(elapsedTime);
            }
            else
            {
                currentScreen.Update(elapsedTime);
            }
#endif
        }

        /// <summary>
        /// Zeichnet den Aktuellen Screen
        /// </summary>
        /// <param name="elapsedTime">Die vergangene Zeit seit dem letzten Update.</param>
        public static void Draw(float elapsedTime)
        {
#if !DEBUG
            try
            {
                Data.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, Data.st, DepthStencilState.None, RasterizerState.CullNone);
                currentScreen.Render(elapsedTime);
                if (overlayScreen != null) { overlayScreen.Render(elapsedTime); }
                spriteBatch.End();
            }
            catch (CubeWorldsException ex)
            {
                CloseOverlayScreen();
                SetScreen(new ScreenManager.CrashScreen(ex));
            }
            catch (Exception e)
            {
                CloseOverlayScreen();
                SetScreen(new ScreenManager.CrashScreen(e));
            }
#endif
#if DEBUG
            Data.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, Data.st, DepthStencilState.None, RasterizerState.CullNone);
            currentScreen.Render(elapsedTime);
            if (overlayScreen != null) { overlayScreen.Render(elapsedTime); }
            spriteBatch.End();
#endif
        }

        /// <summary>
        /// Zeichnet die Welt
        /// </summary>
        /// <param name="elapsedTime">Die vergangene Zeit seit dem letzten Update.</param>
        public static void DrawWorld(float elapsedTime)
        {
            fpsCounter.Draw(elapsedTime);

            MainGame.Device.DepthStencilState = DepthStencilState.Default;
            MainGame.Device.SamplerStates[0] = st;
            world.Draw();
            player.Draw();

            spriteBatch.Draw(kreuz, kreuzPos, Color.White);
            if (isDebugMode)
            {
                spriteBatch.DrawString(debugFont, "Checkable Chunks: " + Data.world.checkableChunks.Count + " X: " + Data.camera.Position.X + " Y: " + Data.camera.Position.Y + " Z: " + Data.camera.Position.Z, new Vector2(10, 10), Color.Black);
                spriteBatch.DrawString(debugFont, "FPS: " + fpsCounter.FPS + " | UPS: " + fpsCounter.UPS, new Vector2(10, 30), Color.Black);
                //spriteBatch.DrawString(debugFont, "X: " + world.x + " XM: " + world.xm + " Z: " + world.z + " ZM: " + world.zm, new Vector2(10, 70), Color.Black);
            }
        }

        /// <summary>
        /// Ändert den aktuellen Screen
        /// </summary>
        /// <param name="screen">Screen der angezeigt werden soll.</param>
        public static void SetScreen(Screen screen)
        {
#if !DEBUG
            try
            {
                currentScreen = screen;
                currentScreen.Init();
            }
            catch (CubeWorldsException ex)
            {
                CloseOverlayScreen();
                SetScreen(new ScreenManager.CrashScreen(ex));
            }
            catch (Exception e)
            {
                CloseOverlayScreen();
                SetScreen(new ScreenManager.CrashScreen(e));
            }
#endif
#if DEBUG
            currentScreen = screen;
            currentScreen.Init();
#endif
        }

        /// <summary>
        /// Setzt den Overlay Screen wird der Overlay Screen gesetzt wird der andere Screen nicht mehr geupdatet aber weiterhin drunter gezeichnet.
        /// </summary>
        /// <param name="screen">Screen der vorm anderen Screen angezeigt werden soll.</param>
        public static void SetOverlayScreen(Screen screen)
        {
#if !DEBUG
            try {
                overlayScreen = screen;
                overlayScreen.Init();
            }
            catch (CubeWorldsException ex)
            {
                CloseOverlayScreen();
                SetScreen(new ScreenManager.CrashScreen(ex));
            }
            catch (Exception e)
            {
                CloseOverlayScreen();
                SetScreen(new ScreenManager.CrashScreen(e));
            }
#endif
#if DEBUG
            overlayScreen = screen;
            overlayScreen.Init();
#endif
        }

        /// <summary>
        /// Schließt den Overlay Screen
        /// </summary>
        public static void CloseOverlayScreen()
        {
            overlayScreen = null;
        }

        /// <summary>
        /// Ändert die Maus sichtbarkeit.
        /// </summary>
        /// <param name="visible"></param>
        public static void changeMouse(bool visible)
        {
            MainGame.MouseVisible = visible;
        }

        /// <summary>
        /// Please edit this comment but i don't now what that do.
        /// </summary>
        public static void redrawScreen()
        {
            kreuzPos = new Vector2(graphics.PreferredBackBufferWidth * 0.5f - 10, graphics.PreferredBackBufferHeight * 0.5f - 10);
        }

    }
}
